/*******************************************************************************
/
/ mapa.cpp
/
/ Creado por Roberto García Carvajal.
/
/ Clase para el manejo de mapas. Usa un formato de fichero particular. 
/ Incluye un identificador calculado con md5 para diferenciar los mapas.
/
/ Documento bajo licencia GPL.
/
*******************************************************************************/

#include <iostream>
#include <fstream>
#include <cstring>
#include "mapa.h"
#include "md5.h"

using namespace std;

// Modo debug.
#define _C_MAPA_DEBUG_ 0

c_mapa::c_mapa()
{
 md5sum[0] = '\0';
 m_mapa = NULL;
 m_ancho = 0;
 m_alto = 0;
 m_fich[0] = '\0';
}

c_mapa &c_mapa::operator=(const c_mapa &m)
{
 if(this != &m)
 {
  this->m_MV = m.m_MV;
  this->m_mV = m.m_mV;
  this->m_PV = m.m_PV;
  this->m_ancho = m.m_ancho;
  this->m_alto = m.m_alto;
  strcpy(this->md5sum,m.md5sum);
  strcpy(this->m_fich,m.m_fich);
 
 
  this->m_mapa = new char*[this->m_alto];
  for(unsigned int i = 0;i < this->m_alto;i++)
   this->m_mapa[i] = new char[this->m_ancho];
  for(unsigned int j = 0;j < this->m_alto;j++)
   for(unsigned int i = 0;i < this->m_ancho;i++)
    this->m_mapa[j][i] = m.m_mapa[j][i];
 }
 return *this;
}

c_mapa::c_mapa(const c_mapa& m)
{
 m_MV = m.m_MV;
 m_mV = m.m_mV;
 m_PV = m.m_PV;
 m_ancho = m.m_ancho;
 m_alto = m.m_alto;
 strcpy(md5sum,m.md5sum);
 strcpy(m_fich,m.m_fich);

 
 m_mapa = new char*[m_alto];
 for(unsigned int i = 0;i < m_alto;i++)
  m_mapa[i] = new char[m_ancho];

 for(unsigned int j = 0;j < m_alto;j++)
  for(unsigned int i = 0;i < m_ancho;i++)
   m_mapa[j][i] = m.m_mapa[j][i];
}

void c_mapa::asociar(char * fich)
{
 delete m_mapa;
 m_mapa = new char*[m_alto];
 for(unsigned int i = 0;i < m_alto;i++)
  m_mapa[i] = new char[m_ancho];
 
 fstream fmapa(fich,ios_base::in);
 {
  for(unsigned int j = 0;j < m_alto;j++)
   for(unsigned int i = 0;i < m_ancho;i++)
   {
    fmapa >> m_mapa[j][i];
   }
 }
 fmapa.close();
}

c_mapa::c_mapa(char * fich)
{
 fstream fmapa(fich,ios_base::in);
 {
  strcpy(m_fich,fich);
  char ctemp;
  int Mversion,mversion,pversion;
  fmapa >> Mversion;
  fmapa >> ctemp;
  fmapa >> mversion;
  fmapa >> ctemp;
  fmapa >> pversion;
  fmapa >> ctemp;
  if(Mversion == C_MAPA_MAJOR_VERSION && mversion == C_MAPA_MINOR_VERSION && pversion == C_MAPA_PATCH_VERSION)
  {
   fmapa >> m_ancho;
   fmapa >> ctemp;
   fmapa >> m_alto;
   fmapa >> ctemp;
   for(unsigned int i = 0;i < 32;i++)
    fmapa >> md5sum[i];
   md5sum[32] = '\000';
   fmapa >> ctemp;
   regenerar();
    
   for(unsigned int i = 0;i < m_alto;i++)
    for(unsigned int j = 0;j < m_ancho;j++)
     fmapa >> m_mapa[i][j];
   
   if(_C_MAPA_DEBUG_)
   {
    for(unsigned int i = 0;i < m_alto;i++)
    {
     for(unsigned int j = 0;j < m_ancho;j++)
      cout << (int)m_mapa[i][j];
     cout << endl;
    }
    cout << m_ancho << endl;
    cout << m_alto << endl;
    cout << md5sum << endl;
   }
  }
 }
 fmapa.close();
}

void c_mapa::cargar(char * fich)
{
 //destruir();
 fstream fmapa(fich);
 {
  strcpy(m_fich,fich);
  char ctemp;
  int Mversion,mversion,pversion;
  fmapa >> Mversion;
  fmapa >> ctemp;
  fmapa >> mversion;
  fmapa >> ctemp;
  fmapa >> pversion;
  fmapa >> ctemp;
  m_MV = Mversion;
  m_mV = mversion;
  m_PV = pversion;
  if(Mversion == C_MAPA_MAJOR_VERSION && mversion == C_MAPA_MINOR_VERSION && pversion == C_MAPA_PATCH_VERSION)
  {
   fmapa >> m_ancho;
   fmapa >> ctemp;
   fmapa >> m_alto;
   fmapa >> ctemp;
   for(unsigned int i = 0;i < 32;i++)
    fmapa >> md5sum[i];
   md5sum[32] = '\000';
   fmapa >> ctemp;
   
   regenerar();
    
   for(unsigned int i = 0;i < m_alto;i++)
    for(unsigned int j = 0;j < m_ancho;j++)
     fmapa >> m_mapa[i][j];
   
   if(_C_MAPA_DEBUG_)
   {
    for(unsigned int i = 0;i < m_alto;i++)
    {
     for(unsigned int j = 0;j < m_ancho;j++)
      cout << (int)m_mapa[i][j];
     cout << endl;
    }
    cout << m_ancho << endl;
    cout << m_alto << endl;
    cout << md5sum << endl;
   }
  }
 }
 fmapa.close();
}

void c_mapa::salvar(char * fich)
{
 unsigned char * temp;
 temp = new unsigned char[m_ancho*m_alto];
 for(unsigned int i = 0;i < m_alto;i++)
  for(unsigned int j = 0;j < m_ancho;j++)
   temp[i*m_alto+j] = (unsigned)m_mapa[i][j];
 MD5 md5;
 md5.update(temp,m_ancho*m_alto);
 md5.finalize();
 strcpy(md5sum,md5.hex_digest());

 fstream mapafich(fich,ios_base::out);
 {
  mapafich << C_MAPA_MAJOR_VERSION;
  mapafich << '-';
  mapafich << C_MAPA_MINOR_VERSION;
  mapafich << '-';
  mapafich << C_MAPA_PATCH_VERSION;
  mapafich << '-';
  
  mapafich << m_ancho;
  mapafich << '-';
  mapafich << m_alto;
  mapafich << '-';
  mapafich << md5sum;
  mapafich << '-';
  cout << md5sum << endl;
  
  for(unsigned int i = 0;i < m_alto;i++)
   for(unsigned int j = 0;j < m_ancho;j++)
    mapafich << m_mapa[i][j];
  
 }
 mapafich.close();
}

void c_mapa::destruir()
{
 if(m_mapa != NULL)
 {
  for(unsigned int i = 0;i < m_alto;i++)
   if(m_mapa[i] != NULL)
    delete m_mapa[i];
  
  delete m_mapa;
 }
}

void c_mapa::md5(char * MD5)
{
 strcpy(md5sum,MD5);
}

void c_mapa::regenerar()
{
 m_mapa = new char*[m_alto];
  for(unsigned int i = 0; i < m_alto;i++)
  {
   m_mapa[i] = new char[m_ancho];
   for(unsigned int j = 0;j < m_ancho;j++)
    m_mapa[i][j] = 0;
  }
}

void c_mapa::nombrefichero(char * fich)
{
 strcpy(m_fich,fich);
}

